#ifndef __MATRIX_H__
#define __MATRIX_H__

template<typename T>
class Matrix
{
public:
  struct RowRef
  {
    RowRef( int w, T* ptr = NULL ) : ptr_(ptr), width(w)
    {
    }

    T& operator [] (int i) 
    {
      assert(i<width);
      return ptr_[i];
    }
  private:
    T* ptr_;
    int width;
  };

  struct ConstRowRef
  {
    ConstRowRef( int w, const T* ptr = NULL ) : ptr_(ptr), width(w)
    {
    }

    T operator [] (int i) const 
    {
      assert(i<width);
      return ptr_[i];
    }
  private:
    const T* ptr_;
    int width;
  };

  RowRef operator [] (int i) 
  {
    assert(i < m_heigiht);
    return RowRef(m_width, m_data[i]);
  }

  ConstRowRef operator [] (int i) const
  {
    assert(i < m_heigiht);
    return ConstRowRef(m_width, m_data[i]); 
  }

protected:
  T** m_data;
  int m_width, m_heigiht;

public:
  Matrix(int width, int height)
  {
    m_width = width;
    m_heigiht = height;
    
    m_data = new T*[m_heigiht];
    for(int i=0; i<m_heigiht; i++)
      m_data[i] = new T[m_width];
  }

  T Get(int i, int j)
  {
    assert(i < m_heigiht && j < m_width);
    return m_data[i*m_width + j];
  }

  void Set(int i, int j, T value)
  {
    assert(i < m_heigiht && j < m_width);
    m_data[i*m_width + j] = value;
  }
};

#endif